#include "qpropertylistview.h"

#include "qpropertybaseeditor.h"

#include "../stylehelper.h"

#include "../../shared/property/qabstractproperty.h"
#include "../../shared/qpropertyfactory.h"


#include <QItemDelegate>
#include <QPainter>
#include <QApplication>
#include <QHeaderView>
#include <QMetaObject>
#include <QMetaProperty>
#include <QPalette>
#include <QMouseEvent>

QWidget *QPropertyEditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
{
    QWidget *wid=NULL;
    if(index.column()==1)
    {
        QTreeWidgetItem *item=m_listView->indexToItem(index);
        QAbstractProperty *property=m_listView->itemToProperty(item);
        if(property!=NULL && property->get_attribute(ATTR_EDITABLE).toBool())
        {
            wid=new QPropertyBaseEditor(property,m_listView->m_undo_stack,parent);
        }
    }
    return wid;
}


void QPropertyEditorDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect.adjusted(0,0,0,-1));
}

void QPropertyEditorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{

}


QPropertyListView::QPropertyListView(QWidget *parent):
    QTreeWidget(parent)
{
    setFrameStyle(QFrame::NoFrame);
    setIconSize(QSize(18, 18));
    setColumnCount(2);
    QStringList labels;
    labels.append(tr("Property"));
    labels.append(tr("Value"));
    setHeaderLabels(labels);
    setAlternatingRowColors(true);
    setEditTriggers(QAbstractItemView::EditKeyPressed);
    setRootIsDecorated(false);
    header()->setMovable(false);

    m_delegate=new QPropertyEditorDelegate(this);
    setItemDelegate(m_delegate);

    m_expandIcon=StyleHelper::drawIndicatorIcon(this->palette(),this->style());

    QPalette p=this->palette();
    p.setColor(QPalette::Inactive,QPalette::Highlight,p.color(QPalette::Active,QPalette::Highlight));
    p.setColor(QPalette::Inactive,QPalette::HighlightedText,p.color(QPalette::Active,QPalette::HighlightedText));
    this->setPalette(p);
}

void QPropertyListView::setPropertys(const QList<QAbstractProperty *> &propertys)
{
    clearAll();
    m_propertys=propertys;
    updateView();
}

void QPropertyListView::clearAll()
{
    QMapIterator<QAbstractProperty*,QTreeWidgetItem*>              it(m_propertyToItem);
    while(it.hasNext())
    {
        it.next();
        it.key()->set_attribute("expanded",it.value()->isExpanded());
    }
    foreach(QAbstractProperty* pro,m_propertys)
    {
        disconnect(pro,SIGNAL(value_chaged(QVariant,QVariant)),this,SLOT(property_changed()));
        disconnect(pro,SIGNAL(edit_value(QVariant)),this,SLOT(property_edit(QVariant)));
    }

    this->clear();
    m_groupItems.clear();
    m_propertyToItem.clear();
    m_itemToProperty.clear();
    m_groups.clear();
}

void QPropertyListView::updateView()
{
    foreach(QAbstractProperty* pro,m_propertys)
    {
        insertItem(pro);
    }
}

void QPropertyListView::insertItem(QAbstractProperty *property, QAbstractProperty *parent)
{
    if(property==NULL)
    {
        return;
    }
    if(!property->get_attribute(ATTR_VISIBLE).toBool())
    {
        return;
    }
    QTreeWidgetItem *parentItem;
    if(parent==NULL)
    {
        QString str=property->get_attribute("group").toString();
        if(str=="")
        {
            str=tr("Common");
        }
        parentItem=m_groupItems.value(str);
        if(parentItem==NULL)
        {
            parentItem=new QTreeWidgetItem(this);
            parentItem->setText(0,str);
            parentItem->setIcon(0,m_expandIcon);
            parentItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
            m_groupItems.insert(str,parentItem);
            m_groups.append(parentItem);
            parentItem->setExpanded(true);
            for(int i=0;i<2;i++)
            {
                parentItem->setData(i,DarkRole,true);
            }
        }
    }
    else
    {
        parentItem=m_propertyToItem.value(parent);
    }
    if(parentItem==NULL)
    {
        return;
    }
    QTreeWidgetItem *item=new QTreeWidgetItem(parentItem);
    item->setText(0,property->get_attribute("show_name").toString());
    item->setToolTip(0,property->get_attribute("show_name").toString());
    item->setText(1,property->get_value_text());
    item->setToolTip(1,property->get_value_text());
    item->setIcon(1,property->get_value_icon());
    item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
    item->setExpanded(property->get_attribute("expanded").toBool());
    m_itemToProperty.insert(item,property);
    m_propertyToItem.insert(property,item);
    connect(property,SIGNAL(value_chaged(QVariant,QVariant)),this,SLOT(property_changed()));
    connect(property,SIGNAL(edit_value(QVariant)),this,SLOT(property_edit(QVariant)));

    QList<QAbstractProperty*>    pros=property->get_children();
    foreach(QAbstractProperty* pro,pros)
    {
        insertItem(pro,property);
    }
}

QTreeWidgetItem *QPropertyListView::indexToItem(const QModelIndex &index) const
{
    return itemFromIndex(index);
}

QAbstractProperty  * QPropertyListView::itemToProperty(QTreeWidgetItem *item) const
{
    return m_itemToProperty.value(item,NULL);
}

bool QPropertyListView::isGroupItem(QTreeWidgetItem *item)const
{
    return m_groupItems.values().contains(item);
}

int QPropertyListView::groupIndex(QTreeWidgetItem *item) const
{
    return m_groups.indexOf(item);
}

void QPropertyListView::mousePressEvent(QMouseEvent *event)
{
    QTreeWidget::mousePressEvent(event);

    QTreeWidgetItem *item=itemAt(event->pos());

    if(item)
    {
        if(m_groupItems.values().contains(item))
        {
            if(event->pos().x()+header()->offset()<20)
            {
                item->setExpanded(!item->isExpanded());
            }
        }
        else
        {
            if(header()->logicalIndexAt(event->pos())==1 && event->button()==Qt::LeftButton)
            {
                editItem(item,1);
            }
        }
    }
}

void QPropertyListView::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
{
    QColor c;
    QStyleOptionViewItem opt=options;
    if(index.data(DarkRole).toBool())
    {
        c=opt.palette.color(QPalette::Dark);
    }
    else
    {
        c=QColor(BACKGROUND_COLOR);
    }


    painter->fillRect(options.rect,c);
    opt.palette.setColor(QPalette::AlternateBase,c.lighter(112));
    QTreeWidget::drawRow(painter,opt,index);

    QColor color=static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor));
    painter->setPen(color);
    painter->drawLine(opt.rect.x(),opt.rect.bottom(),opt.rect.right(),opt.rect.bottom());

}

void QPropertyListView::property_changed()
{
    QAbstractProperty* pro=(QAbstractProperty*)sender();
    QTreeWidgetItem *item=m_propertyToItem.value(pro);
    if(item==NULL)
    {
        return;
    }
    item->setText(1,pro->get_value_text());
    item->setToolTip(1,pro->get_value_text());
    item->setIcon(1,pro->get_value_icon());
    this->update(indexFromItem(item));
    emit active();
}

void QPropertyListView::property_edit(const QVariant &value)
{
    emit property_edit_signal((QAbstractProperty*)sender(),value);
}

void QPropertyListView::set_undo_stack(QUndoStack *stack)
{
    m_undo_stack=stack;
}
